package org.budo.support.java.concurrent.executor;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author lmw
 */
public class ExecutorUtil {
    /**
     * 在限定时间内执行一段代码并返回值
     * 
     * @param callable 被执行的代码
     * @param timeout 超时时间 MILLISECONDS
     */
    public static <T> T executeAndGet(Callable<T> callable, Integer timeout) {
        FutureTask<T> futureTask = new FutureTask<T>(callable);

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(futureTask);

        try {
            return futureTask.get(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            futureTask.cancel(true);
            throw new RuntimeException("#31 timeout=" + timeout + ", callable=" + callable, e);
        } catch (ExecutionException e) {
            futureTask.cancel(true);
            throw new RuntimeException("#34 timeout=" + timeout + ", callable=" + callable, e);
        } catch (TimeoutException e) {
            futureTask.cancel(true);
            throw new RuntimeException("#37 timeout=" + timeout + ", callable=" + callable, e);
        } finally {
            executorService.shutdown();
        }
    }

    /**
     * @param timeout 超时时间 MILLISECONDS
     */
    public static void execute(final Runnable runnable, Integer timeout) {
        executeAndGet(new Callable<Object>() {
            public Object call() throws Exception {
                runnable.run();
                return null;
            }
        }, timeout);
    }
}